﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Entities;
using DAOBase;
using BusinessExceptions;
using Interfaces;

namespace Business
{
    public class BusinessLogic
    {
        private int cur_id = 0;
        private DaoFacade facade;
        private IUserDAO userDao;
        private IInterviewDAO intervDao;
        private IRoleDAO roleDao;

        public BusinessLogic()
        {
            this.facade = new DaoFacade();
            this.userDao = this.facade.GetFactory().GetUserDAO();
            this.intervDao = this.facade.GetFactory().GetInterviewDAO();
            this.roleDao = this.facade.GetFactory().GetRoleDAO();
        }

        public void DeleteInterview(int intervID)
        {
            this.intervDao.RemoveInterview(intervID);
        }

        public Interview LoadInterview(int intervID)
        {
            return this.intervDao.LoadInterview(intervID);
        }

        public List<Interview> GetInterviewsForRole(string role)
        {
            if (role == "admin" || role == "moderator")
            {
                return this.intervDao.GetAllInterviews("[state] >= 0 AND [state] <= 2");
            }
            else
            {
                return this.intervDao.GetAllInterviews("[state] = '1'");
            }
        }

        public bool InterviewExist(int intervID)
        {
            return intervDao.InterviewExist(intervID);
        }

        public void CreateInterview(Interview interv)
        {
            if (this.IsValidId(interv.ID))
            {
                throw new BusinessException();  // Collision, already exists
            }
            this.intervDao.NewInterview(interv);
        }

        public int CreateInterviewRet(Interview interv)
        {
            if (this.IsValidId(interv.ID))
            {
                throw new BusinessException();  // Collision, already exists
            }
            return intervDao.NewInterviewRet(interv);
        }


        public void RemoveInterview(int id)
        {
            if (!this.IsValidId(id))
            {
                throw new BusinessException(); // Interview not found
            }
            this.intervDao.RemoveInterview(id);
        }

        public void ModifyInterview(Interview src)
        {
            intervDao.ModifyInterview(src.ID, src);
        }

        public void AddQuestion(int interviewId, Question quest)
        {
            if (!this.IsValidId(interviewId))
            {
                throw new BusinessException(); // Interview not found
            }
            var interv = this.intervDao.LoadInterview(interviewId);
            interv.AddQuestion(quest);
            this.intervDao.ModifyInterview(interviewId, interv);
        }

        public void RemoveQuestion(int interviewId, int questionId)
        {
            if (!this.IsValidId(interviewId))
            {
                throw new BusinessException(); // Interview not found
            }
            var interv = this.intervDao.LoadInterview(interviewId);
            interv.RemoveQuestion(questionId);
            this.intervDao.ModifyInterview(interviewId, interv);
        }

        public void EditQuestion(int interviewId, int questionId, Question quest)
        {
            if (!this.IsValidId(interviewId))
            {
                throw new BusinessException(); // Interview not found
            }
            if (quest == null)
            {
                throw new ArgumentNullException();
            }

            var interv = this.intervDao.LoadInterview(interviewId);
            try
            {
                interv.EditQuestion(questionId, quest);
            }
            catch (IndexOutOfRangeException)
            {
                // Smth
            }
            this.intervDao.ModifyInterview(interviewId, interv);
        }

        public void RunInterview(int interviewId, InterviewRunResultData data)
        {
            if (data == null || interviewId < 0)
            {
                throw new ArgumentException();
            }

            if (!this.intervDao.InterviewExist(interviewId) || !this.userDao.UserExists(data.UserID))
            {
                throw new BusinessException();
            }

            intervDao.SaveInterviewRunResultData(interviewId, data);
        }

        public InterviewResultData GetGenericStatistics(int intervId)
        {
            if (!this.IsValidId(intervId))
            {
                throw new BusinessException();
            }
            return this.intervDao.GetResultDataForInterview(intervId);
        }

        // Danger, can be huge...
        public InterviewRunResultData GetDetailedStatistics(int intervId, int userId)
        {
            if (!this.IsValidId(intervId))
            {
                throw new BusinessException();
            }
            return this.intervDao.GetDetailedStatisticsForInterview(intervId, userId);
        }

        public bool IsValidId(int id)
        {
            return this.intervDao.InterviewExist(id);
        }

        public void AddUser(User src)
        {
            if (!this.userDao.UserExists(src.Login))
            {
                this.userDao.AddUser(src);
            }
        }

        public bool IsValidAuth(User auth)
        {
            return this.userDao.IsValidAuth(auth);
        }

        public Dictionary<int, string> GetRoles()
        {
            return this.roleDao.GetRolesList();
        }

        public List<string> GetUserRoles(string login)
        {
            return this.userDao.GetUser(userDao.GetUserID(login)).Roles;
        }

        public bool InterviewExist(string title)
        {
            return this.intervDao.InterviewExist(title);
        }

        public void SetInterviewState(int id, Entities.Enums.InterviewState state)
        {
            intervDao.SetState(id, state);
        }

        public Entities.Enums.InterviewState GetInterviewState(int id)
        {
            return intervDao.GetState(id);
        }

        public int GetUserID(string login)
        {
            return this.userDao.GetUserID(login);
        }

        public void SaveInterviewRunResult(InterviewRunResultData irrd)
        {
            this.intervDao.SaveInterviewRunResultData(irrd.InterviewID, irrd);
        }
    }
}
